#include "userInput.h"

/**** Handles user input functions ****/
  
/**
 * Creates thread that reads user input from stdin
 */
void * threadUserInput() {
  
  //Variables necessary for threads
  void * userInputString;
  pthread_t inputThread;
	
  //Create thread
  if( pthread_create(&inputThread, NULL, getInput, userInputString)){
	error("Thread");
  }  
} // End threadUserInput

/**
 * Gets User Input as a string of characters.
 * 
 * @param ptr - pointer to return string to
 */
void * getInput(void * ptr) {
  // Boolean to denote whether content has been found or not
  int found;
  
  //Allocate space for string to be read in from keyboard
  //Add 1 to allow for copying of newline character (fgets)
  char inputString[MAX_NAME+2];
  
  // Allocate space for request message
  char reqMessageBuffer[MAX_MSG];
  
  //Continuously loop through user input request
  while (true) {
    
    // Reset to false
    found = false;
    
    //Holds all peers in content directory (unique list)
    struct contentDir allPeers[MAX_DIR];
    
	  //Prompt for user input
	  printf("\nPlease enter the name of a resource to request: ");
	  
	  //Get string from stdin (this will include \n character
	  //Allow only MAX_NAME characters to be input through stdin
	  if (!fgets(inputString, MAX_NAME+2, stdin)){
		  error("Please enter a filename less than 20 characters long");
	  }
	  
	  //Truncate newline character
	  inputString[strlen(inputString)-1] = '\0';
	  
	  //User feedback
	  printf("You requested: %s\n\n", inputString);
	  
    // Look through Local Directory for file
    if (searchList(&listLocalFiles, inputString, 0)){
      found = true;
    }
    
    // Look through Data Cache
    else if (searchList(&dataCacheList, inputString, 1)){ 
      found = true;
    }
    
    if (found){
      printf("Content: %s\nFOUND\n", inputString);
    }
    
    // If not in Local Directory or Data Cache, then send to all peers in content directory
    else {
      // Create request message
      int messageLength = createRequestMessage(inputString, reqMessageBuffer);
      
      // Create outstanding Request
      // 0 - user initiated request
      push (&outstandingRequestsList, createOutstandingReqItem(inputString, 0));
      
      //Send to all peers in content directory
      //Cycle through content directory
      //Get an array containing all unique peers
      int numPeers = allUniquePeers(allPeers);
      
      //Send to all peers in array
      int i;
			
			if (debug) {
				printMessage((unsigned char *) reqMessageBuffer, messageLength);
				printf("NUMPEERS: %d\n", numPeers);
			}

      for (i = 0; i < numPeers; i++){
				if (debug) {
					printf("SENDING TO: %s, PORT: %d\n", ipToString(allPeers[i].address), allPeers[i].port);
      	}
				sendUDP(ipToString(allPeers[i].address), (allPeers[i].port), socketfd, (unsigned char *)reqMessageBuffer, messageLength);
      }
    } // End else
    
	  
  } // End while loop	
}

/**
 * Creates a unique list of all peers in the content directory
 *
 * @param array[] - an array of pointers to address/port combinations
 * @return countPeers - number of unique peers
 */
int allUniquePeers(struct contentDir array[]){
  
  //Flag denotes whether this peer is unique
  int uniquePeer;
  
  int countPeers = 0;
  
  struct node * iter = createIterator(contentDirectoryList);
  struct node * trashIter = iter;
  struct contentDir * tempContentDir;
  
  //iterate through the list
  while (hasNext(iter)){
  
  	uniquePeer = true;
  	
  	next(&iter);
  	tempContentDir = (struct contentDir *) (iter->payload);
  	
  	int i;
  	
  	// Check if a duplicate exists in the array storing unique
  	// peers in content directory
  	for (i = 0; i < countPeers; i++){
  		
  		int sameAddress = false;
  		int samePort = false;
  		
  		if (tempContentDir->address == array[i].address){
  			sameAddress = true;
  		}
  		
  		if (tempContentDir->port == array[i].port){
  			samePort = true;
  		}
  		
  		// If both the port and address are the same we don't add
  		// this peer.
  		if(samePort && sameAddress){
  		  uniquePeer = false;
  		}
  	}
  	
  	//store in struct array if it's unique
  	if(uniquePeer){
  		array[countPeers].address = tempContentDir->address;
  		array[countPeers].port = tempContentDir->port;
  		countPeers++;
  	}
  }
  
  free(trashIter);
  return countPeers;
}

/*
 * Creates a request message
 *
 * @param name - filename
 * @param reqMsgBuffer - buffer to store request message in
 * @return messageLength - length of message
 */
int createRequestMessage(char * name, char * reqMsgBuffer){
  int messageLength = 0;
  
  // Add in required header info
  reqMsgBuffer[0] = 0xCC;
  reqMsgBuffer[1] = 0x52;
  
  // add to message length
  messageLength += 2;
  
  // Copy in name to buffer
  strcpy(&reqMsgBuffer[messageLength], name);
  
  // Add to message length and add one for null-terminating 0
  messageLength += strlen(name) + 1;
  
  if (debug){
    printf("\nREQ MESSAGE: ");
    printMessage((unsigned char *)reqMsgBuffer, messageLength);
  }
  
  return messageLength;

} // End createRequestMessage




















